/**
 * Copyright 2000 self.com.au
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License. (http://www.apache.org/licenses/LICENSE-2.0)
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed 
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for 
 * the specific language governing permissions and limitations under the License.
 *
 * <dhamma-message src="Atisha (11th century Tibetan Buddhist master)">
 * 	The greatest achievement is selflessness. The greatest worth is self-mastery.
 * 	The greatest quality is seeking to serve others. The greatest precept is continual awareness.
 * 	The greatest medicine is the emptiness of everything. The greatest action is not conforming with the worlds ways.
 * 	The greatest magic is transmuting the passions. The greatest generosity is non-attachment.
 * 	The greatest goodness is a peaceful mind. The greatest patience is humility.
 * 	The greatest effort is not concerned with results. The greatest meditation is a mind that lets go.
 * 	The greatest wisdom is seeing through appearances. 
 * </dhamma-message>
 *
 * @author Ashin Wimalajeewa
 */
package self.amigo.editor.cmd;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import self.gee.IDiagramLayer;
import self.gee.IGraphicElement;
import self.gee.ILinkGraphic;
import self.gee.ILinkableGraphic;
import self.gee.editor.ICommand;
import self.gee.editor.IDiagramEditor;

public class SelectionDeletion implements ICommand {
	
  private IDiagramEditor  editor;
  private IDiagramLayer   layer;
  
  private List             selection = new ArrayList();
  private Map              attachmentsMap = new HashMap();
  private Map              linksMap = new HashMap();
  
//  public SelectionDeletion( IDiagramEditor ed, List sel ) {
  public SelectionDeletion( IDiagramEditor ed ) {
    editor = ed;
    layer = editor.getSource().getContext();
//    selection.addAll( sel );
    ed.getSelectedElements( selection );
//    dumpSelection();
    buildAttachmentsMap();
  }
  
  public void execute() {
    editor.setDeleting( true );
    try {
      List refreshedElements = SelectionUtils.toNewElementList( selection, layer );
      layer.beginUpdate();
      int max = selection.size();
      for ( int cntr = 0; cntr < max; cntr++ ) {
        IGraphicElement elem = (IGraphicElement) refreshedElements.get( cntr );
        elem.remove();
      }    
      layer.endUpdate();
      editor.setSelectedElements( Collections.EMPTY_LIST );
      editor.inspectSelectedObjects( Collections.EMPTY_LIST );
    } finally {
      editor.setDeleting( false );
    }
    editor.getSource().redraw();
  }
  
  public void undo() {
    layer.beginUpdate();
    recreateSelectionTree();
    layer.endUpdate();
    editor.setSelectedElements( selection );
    editor.inspectSelectedObjects( selection );
    editor.getSource().redraw();
  }

  private void recreateSelectionTree() {
    int max = selection.size();
    for ( int cntr = 0; cntr < max; cntr++ ) {
      IGraphicElement elem = (IGraphicElement) selection.get( cntr );
      insertElementIntoTree( elem );
    }
  }
  
  private void insertElementIntoTree( IGraphicElement elem ) {
    elem.setLayer( layer, true );
    if ( elem instanceof ILinkableGraphic ) 
      attachShakers( (ILinkableGraphic) elem );
    if ( elem instanceof ILinkGraphic )
      resolveLink( (ILinkGraphic) elem );
  }
  
  private void attachShakers( ILinkableGraphic elem ) {
    List shakers = (List) attachmentsMap.get( elem );
    int max = shakers.size();
    for ( int cntr = 0; cntr < max; cntr++ ) {
      ILinkGraphic shaker = (ILinkGraphic) shakers.get( cntr );
      elem.attachElement( shaker );
      insertElementIntoTree( shaker );
    }
  }
  
  private void resolveLink( ILinkGraphic elem ) {
    LinkEntry entry = (LinkEntry) linksMap.get( elem );
    elem.linkSideA( entry.sideA );
    elem.linkSideB( entry.sideB );
  }
  
  private void buildAttachmentsMap() {
    int max = selection.size();
    for ( int cntr = 0; cntr < max; cntr++ ) {
      IGraphicElement elem = (IGraphicElement) selection.get( cntr );
      if ( elem instanceof ILinkableGraphic ) 
        mapLinkableAttachments( (ILinkableGraphic) elem );
      if ( elem instanceof ILinkGraphic )
        addLinkEntryToMap( (ILinkGraphic) elem );
    }
  }
  
  private void mapLinkableAttachments( ILinkableGraphic elem ) {
    if ( attachmentsMap.containsKey(elem) )
      return;
    List shakers = new ArrayList();
    ((ILinkableGraphic) elem).getAttachments( shakers );
    attachmentsMap.put( elem, shakers );
    int max = shakers.size();
    for ( int cntr = 0; cntr < max; cntr++ ) {
      IGraphicElement shaker = (IGraphicElement) shakers.get( cntr );
      if ( shaker instanceof ILinkGraphic ) 
        addLinkEntryToMap( (ILinkGraphic) shaker );
      if ( shaker instanceof ILinkableGraphic ) 
        mapLinkableAttachments( (ILinkableGraphic) shaker );
    }
  }

  private void addLinkEntryToMap( ILinkGraphic elem ) {
    if ( !linksMap.containsKey(elem) )
      linksMap.put( elem, new LinkEntry((ILinkGraphic) elem) );
  }
  
  private class LinkEntry {
    public ILinkableGraphic sideA, sideB;
    
    public LinkEntry( ILinkGraphic src ) {
      sideA = src.getSideA();
      sideB = src.getSideB();
    }
  }
}